#include "boot_av.h"

#if (defined _BOARD_DB_M3511_01V01_ || \
     defined _BOARD_DB_M3822_01V01_)

static struct pe_video_cfg_extra video_cfg_extra;
static struct pe_video_cfg video_cfg;

extern int video_engine_decode(char *video_file, UINT8 video_stream_type, enum SndDupChannel audio_channel, BOOL preview);
extern int video_engine_init(struct pe_video_cfg *pe_video_cfg);

static void bl_mp_apcallback(UINT32 event_type,UINT32 param)
{
	FIXED_PRINTF("%s(): event_type = %d, param=%d\n",__FUNCTION__, event_type, param);
    switch(event_type)
    {
        case MP_VIDEO_PLAYBACK_END:
            set_videologo_playback_status(1);
            break;
        default:
            break;
            
    }

	return;
}

static void bl_mp_init(UINT8 *logo_buf, UINT32 logo_len)
{
    video_cfg_extra.frame_buf_base = 0;
    video_cfg_extra.frame_buf_len = 0;
    video_cfg_extra.reserved[0] = logo_buf;
    video_cfg_extra.reserved[1] = logo_len;
    
    video_cfg.decoder_buf = __MM_VIDEO_FILE_BUF_ADDR;
    video_cfg.decoder_buf_len = __MM_VIDEO_FILE_BUF_LEN;
    video_cfg.disable_seek = TRUE;
    video_cfg.mp_cb = bl_mp_apcallback;
    video_cfg.new_retry_mechanism = FALSE;
    video_cfg.reserved = ((UINT32)(&video_cfg_extra)|0xA0000000);
    video_cfg.mm_vbv_len = 0;

    osal_cache_flush(&video_cfg_extra,sizeof(struct pe_video_cfg_extra));
    osal_cache_flush(&video_cfg,sizeof(struct pe_video_cfg));
    
    video_engine_init((UINT32)(&video_cfg)|0xA0000000);
}

static void bl_mp_start()
{
    video_engine_decode("logo.mpg", MPEG_12_FILE_STREAM, SND_DUP_NONE, FALSE);
}

void bl_deca_attach(void)
{
    struct deca_feature_config deca_config;

    MEMSET(&deca_config, 0, sizeof(struct deca_feature_config)); 
    deca_config.detect_sprt_change = 1;
    deca_m36_attach(&deca_config);

    return;
}

void bl_snd_attach(void)
{
    struct snd_feature_config snd_config;
    MEMSET(&snd_config, 0, sizeof(struct snd_feature_config));    
	snd_config.output_config.mute_num = 19;
	snd_config.output_config.mute_polar 	= 0;
	snd_config.output_config.dac_precision = 24;
	snd_config.output_config.dac_format 	= 0;
	snd_config.output_config.is_ext_dac 	= 0;
	snd_config.output_config.ext_mute_mode = 0;	
	snd_config.support_spdif_mute = 1;
    snd_config.output_config.chip_type_config = 1; //QFP
	snd_config.support_desc = 0;
    //snd_config.support_desc |= SND_SUPPORT_DDPLUS;

    snd_m36g_attach(&snd_config);

    return;
}

void bl_deca_open(void)
{
    struct deca_device *deca_dev = NULL;
    
    deca_dev = (struct deca_device *)dev_get_by_id(HLD_DEV_TYPE_DECA, 0);
	if(RET_SUCCESS!=deca_open(deca_dev, AUDIO_MPEG2, AUDIO_SAMPLE_RATE_48, AUDIO_QWLEN_24, 2, 0))
	{
		ASSERT(0);
	}
    deca_io_control(deca_dev,DECA_SET_STR_TYPE,AUDIO_MPEG2); 
    return;
}

void bl_snd_open(void)
{
    struct snd_device *snd_dev = NULL;
    
    snd_dev = (struct snd_device *)dev_get_by_id(HLD_DEV_TYPE_SND, 0);
	if(RET_SUCCESS!=snd_open(snd_dev))
	{
		ASSERT(0);
	}

    snd_io_control(snd_dev, FORCE_SPDIF_TYPE, SND_OUT_SPDIF_INVALID);
	snd_io_control(snd_dev, FORCE_SPDIF_TYPE, SND_OUT_SPDIF_PCM);		

    snd_set_volume(snd_dev, SND_SUB_OUT, 50);
    
    return;
}

/* First Video Frame Already Show */
static void cb_vdec_first_show(UINT32 uParam1, UINT32 uParam2)
{
    struct TRANS_VDEC_INFO vdec_info;
    struct VDec_StatusInfo vdec_status;

    MEMSET(&vdec_status, 0, sizeof(vdec_status));
    vdec_io_control((struct vdec_device *)dev_get_by_id(HLD_DEV_TYPE_DECV, 0), VDEC_IO_GET_STATUS, (UINT32)&vdec_status);
    
	vdec_info.pic_width = vdec_status.pic_width;
    vdec_info.pic_height = vdec_status.pic_height;
    vdec_info.aspect_ratio = vdec_status.aspect_ratio;
    vdec_info.resv[0] = 1;
    set_sysinfo_from_bl(TRANS_VDEC_TYPE, (UINT8 *)&vdec_info);
}

RET_CODE bl_show_av(UINT8 *buf, UINT32 len)
{
	RET_CODE ret_code = RET_FAILURE;
    UINT32 req_size;
	UINT32 got_size;
    INT32 repeat_time;
	INT32 left_size = len;
	char *temp_buf = buf;
	void *pwrite_buff = NULL;
	struct de2Hdmi_video_infor llvs;
    struct snd2Hdmi_audio_infor llas;
    UINT8 lastbuf[32] = {0};
    UINT8 tv_mode = 0;
	UINT8 scart_out = 0;
	UINT8 tv_ratio = 0;
    UINT8 display_mode = 0;
    UINT16	screen_width;
	UINT16	screen_height;
    INT32 ret = SUCCESS;
    struct vdec_io_reg_callback_para tpara;
    
	if (buf == NULL)
	{
		LOGO_PRINTF("Logo buffer is null\n");
		return RET_FAILURE;
	}

    ret = bl_get_tv_set(&tv_mode,&scart_out, &tv_ratio, &display_mode);
    if(ret != SUCCESS)
    {
        //set default value
#if 1
        tv_mode = TV_MODE_720P_60;
#else
        tv_mode = TV_MODE_1080I_25;
#endif		
        scart_out = SCART_YUV;
		//tv_ratio = TV_ASPECT_RATIO_169; // 16:9
		tv_ratio = TV_ASPECT_RATIO_AUTO;// aspect default set to auto
		display_mode = DISPLAY_MODE_PANSCAN;
    }

    
	llvs.tv_mode = tvmode_to_tvsys(tv_mode, scart_out);//10;
	llvs.afd_present = TRUE;
	llvs.scan_mode = logo_data_is_progressive(tv_mode);//FALSE;
	llvs.format = 4;
	llvs.output_aspect_ratio = tv_ratio;
	llvs.active_format_aspect_ratio = 8;

    bl_get_show_para(llvs.tv_mode, &screen_width, &screen_height);
	llvs.width = screen_width;
	llvs.height = screen_height;
	llvs.av_chg_ste = HDMI_CB_NOTHING;

	llas.user_def_ch_num = 2;
	llas.pcm_out = 1;
	llas.coding_type = 0x05;
	llas.max_bit_rate = 128000;
	llas.ch_count = 2;
	llas.sample_rate = 48000;
	llas.level_shift = 0;
	llas.spdif_edge_clk = 0;
	llas.ch_status = 0x33554432;
	llas.ch_position[0] = 224;
	llas.ch_position[1] = 242;
	llas.ch_position[2] = 0;
	llas.ch_position[3] = 0;
	llas.ch_position[4] = 0;
	llas.ch_position[5] = 0;
	llas.ch_position[6] = 0;
	llas.ch_position[7] = 0;
	llas.bclk_lrck = 64;
	llas.word_length = 24;
	llas.i2s_edge_clk = 0;
	llas.i2s_format = 0;
	llas.lrck_hi_left = 0;
	llas.av_chg_ste = HDMI_CB_AV_INFO_CHG | HDMI_CB_CLK_CHG_DONE;

	set_scart_gpio();
	vpo_dev_attach();
	vdec_dev_attach();
    bl_deca_attach();
    bl_snd_attach();

	avInit(tv_mode, scart_out, tv_ratio, display_mode);
    bl_deca_open();
    bl_snd_open();
	avStart(llvs.tv_mode, llvs.scan_mode);

	tpara.eCBType = VDEC_CB_FIRST_SHOWED;
	tpara.pCB = cb_vdec_first_show;
	vdec_io_control((struct vdec_device *)dev_get_by_id(HLD_DEV_TYPE_DECV, 0), VDEC_IO_REG_CALLBACK, (UINT32)(&tpara));
    
	/************config_de**************/	
	VOU_CTRL = VOU_CTRL&(~(1<<2));	
	osal_delay(5);
	VOU_CFG_HDMI = VOU_CFG_HDMI|(1<<20);
	osal_delay(5);
	VOU_CFG_HDMI = VOU_CFG_HDMI |0x02;
	osal_delay(5);	
	VOU_CTRL = VOU_CTRL|(1<<2)|0x01;
	/**************config_de*************/
    
	hdmi_show_on_bootloader(&llvs, &llas);
    bl_mp_init(buf, len);
    bl_mp_start();

	return ret_code;
}

#endif

